package com.kuding.config;

import java.util.concurrent.ExecutorService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.support.ExecutorServiceAdapter;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.kuding.config.conditional.ConditionalOnEnableAliyun;
import com.kuding.enums.WhatDoWeHave;

@Configuration
@ConditionalOnEnableAliyun(WhatDoWeHave.LOG)
public class AliyunLogThreadPoolConfig implements AsyncConfigurer {

	public static final String THREAD_EXECUTOR_NAME = "vinusLogThreadExecutor";

	public static final String THREAD_EXCEPTION_HANDLER_NAME = "vinusLogThreadExceptionHandler";

	public static final Log logger = LogFactory.getLog(THREAD_EXCEPTION_HANDLER_NAME);

	@Override
	@Bean(name = THREAD_EXECUTOR_NAME)
	@ConditionalOnMissingBean(name = THREAD_EXECUTOR_NAME)
	public ExecutorService getAsyncExecutor() {
		ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
		poolTaskExecutor.setThreadNamePrefix("vinus-log-");
		poolTaskExecutor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
		poolTaskExecutor.setMaxPoolSize(20);
		poolTaskExecutor.setQueueCapacity(200);
		poolTaskExecutor.setKeepAliveSeconds(60);
		poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
		poolTaskExecutor.setAwaitTerminationMillis(30000);
		poolTaskExecutor.setBeanName(THREAD_EXECUTOR_NAME);
		poolTaskExecutor.initialize();
		ExecutorServiceAdapter adapter = new ExecutorServiceAdapter(poolTaskExecutor);
		return adapter;
	}

	@Override
	@Bean(name = THREAD_EXCEPTION_HANDLER_NAME)
	@ConditionalOnMissingBean(name = THREAD_EXCEPTION_HANDLER_NAME)
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return (x, y, z) -> logger.error("log execute error when execute ".concat(y.getName()), x);
	}

}
